10 REM *** (FFT7.02) FFT/INV FFT ***

11 REM MODIFIES SQUARE FUNCTION SPECTRUM & RECONSTRUCTS

12 SCREEN 9, 1: COLOR 15, 1

13 CLS : PRINT : PRINT "INPUT NUMBER OF DATA POINTS AS 2^N"

14 INPUT "N = "; N

16 Q = 2 ^ N

20 Q2 = Q / 2: Q3 = Q2 - 1: Q4 = Q / 4: Q5 = Q4 - 1: Q8 = Q / 8

21 FMN = 0: FMX = Q: FSTEP = 1

22 DIM Y(Q), C(2, Q), S(2, Q), KC(Q), KS(Q), F(2, (FTOP - FBOT) + 1)

23 DIM COMP(3, KB, KB), Z(2, KB, KB + 1)

24 X0 = 50: Y0 = 200: XSF = 500 / Q: YSF = 150: IOFLG = 1

30 PI = 3.141592653589793#: P2 = 2 * PI: K1 = P2 / Q: PI2 = P2

32 FOR I = 0 TO Q: KC(I) = COS(K1 * I): KS(I) = SIN(K1 * I): NEXT

40 CLS

50 PRINT SPC(30); "MAIN MENU": PRINT : PRINT

52 PRINT SPC(5); "1 = GENERATE STEP FUNCTION & TRANSFORM": PRINT

54 PRINT SPC(5); "2 = FORWARD TRANSFORM": PRINT

56 PRINT SPC(5); "3 = MODIFY SPECTRUM": PRINT

58 PRINT SPC(5); "4 = INVERSE TRANSFORM": PRINT

60 PRINT SPC(5); "5 = MODIFY SYSTEM": PRINT

62 PRINT SPC(5); "6 = EXIT": PRINT

70 PRINT SPC(10); "MAKE SELECTION :";

80 A$ = INKEY$: IF A$ = "" THEN 80

90 A = VAL(A$): ON A GOSUB 600, 100, 1000, 120, 140, 990

95 GOTO 40



100 REM *** FORWARD FFT ***

102 K6 = -1: SK1 = 2

104 CLS : HDR$ = "FREQ   F(COS)       F(SIN)       "

106 HDR$ = HDR$ + "FREQ   F(COS)       F(SIN)": PRINT : PRINT

108 GOSUB 180

RETURN



120 REM *** INVERSE TRANSFORM ***

122 SK1 = 1: K6 = 1

124 CLS : HDR$ = "TIME    AMPLITUDE   NOT USED     "

126 HDR$ = HDR$ + "TIME   AMPLITUDE     NOT USED": PRINT : PRINT

128 GOSUB 180

130 RETURN



140 CLS ' *** MODIFY SYSTEM PARAMETERS ***

142 PRINT "PRESENT DATA GRAPHICALLY? (Y/N):";

144 A$ = INKEY$: IF A$ = "" THEN 144

146 IF A$ = "Y" OR A$ = "y" THEN IOFLG = 1 ELSE IOFLG = -1

148 RETURN



180 REM *** FFT ROUTINE ***

181 T9 = TIMER

182 FOR M = 0 TO N - 1: QT = 2 ^ M: KT1 = 2 ^ (N - M - 1)

183 REM *** UNIVERSAL BUTTERFLY ***

184 FOR J = 0 TO Q3 STEP QT: J1 = 2 * J: K9 = J + Q2

185 FOR I = 0 TO QT - 1: KT = I * KT1: K = K9 + I

187 C(T0, J1 + I) = (C(T1, I + J) + C(T1, K) * KC(KT) - K6 * S(T1, K) * KS(KT)) / SK1

188 S(T0, J1 + I) = (S(T1, I + J) + K6 * C(T1, K) * KS(KT) + S(T1, K) * KC(KT)) / SK1

190 NEXT I

191 J1 = J1 + QT

192 FOR I = 0 TO QT - 1: KT = (I + QT) * KT1: K = K9 + I

194 C(T0, J1 + I) = (C(T1, I + J) + C(T1, K) * KC(KT) - K6 * S(T1, K) * KS(KT)) / SK1

195 S(T0, J1 + I) = (S(T1, I + J) + K6 * C(T1, K) * KS(KT) + S(T1, K) * KC(KT)) / SK1

196 NEXT I: NEXT J

197 IF T0 = 0 THEN T0 = 1: T1 = 0: GOTO 199

198 T0 = 0: T1 = 1

199 NEXT M



200 T9 = TIMER - T9

202 IF IOFLG = 1 THEN 250

206 ZSTP = 15

208 PRINT HDR$: PRINT : PRINT

210 FOR Z = 0 TO Q2 - 1

214 GOSUB 300

216 IF Z > ZSTP THEN 350 ' PRINT 1 SCREEN AT A TIME

220 NEXT Z

222 LOCATE 1, 1: PRINT : PRINT "TIME ="; T9

225 INPUT "C/R TO CONTINUE:"; A$

229 RETURN



250 REM *** PLOT OUTPUT ***

252 CLS : YPX = 0: IF K6 = -1 THEN 280

254 Y0 = 175

256 FOR I = 0 TO Q - 1 ' FIND MAX VALUE IN ARRAY

258 IF C(T1, I) > YPX THEN YPX = C(T1, I)' IF > YPX SWAP

260 NEXT I ' CHECK NEXT DATA POINT

262 YSF = 100 / YPX' SET Y SCALE FACTOR

263 LINE (X0 + 10, Y0 - 100)-(X0, Y0 - 100)

264 LOCATE 6, 1: PRINT USING "###.##"; YPX ' PRINT SCALE FACTOR

265 LINE (X0 - 1, 50)-(X0 - 1, 300)

266 LINE (X0, Y0)-(X0 + 500, Y0)

268 LINE (X0, Y0)-(X0, Y0) ' PEN TO ORIGIN

270 FOR I = 0 TO Q - 1

272 YP = C(T1, I)

274 IF K6 = -1 THEN YP = SQR(C(T1, I) ^ 2 + S(T1, I) ^ 2)

276 LINE -(X0 + XSF * I, Y0 - YSF * YP)

278 NEXT I

279 GOTO 222

280 ' *** FIND Y SCALE FACTOR FOR FREQ DOMAIN PLOT ***

281 Y0 = 300 ' SET Y AXIS ORIGIN

282 FOR I = 0 TO Q - 1' FIND LARGEST VALUE IN ARRAY

284 YP = SQR(C(T1, I) ^ 2 + S(T1, I) ^ 2): IF YP > YPX THEN YPX = YP

286 NEXT I ' CHECK NEXT DATA POINT

287 YSF = 200 / YPX' SET SCALE FACTOR

288 LINE (X0 + 10, Y0 - 200)-(X0, Y0 - 200)

289 LOCATE 8, 1: PRINT USING "###.##"; YPX: GOTO 265



300 PRINT USING "###"; Z; : PRINT "   ";

310 PRINT USING "+##.#####"; C(T1, Z); : PRINT "    ";

312 PRINT USING "+##.#####"; S(T1, Z); : PRINT "      ";

320 PRINT USING "###"; Z + Q2; : PRINT "   ";

322 PRINT USING "+##.#####"; C(T1, Z + Q2); : PRINT "    ";

324 PRINT USING "+##.#####"; S(T1, Z + Q2)

330 RETURN



350 REM ***  STOP WHEN SCREEN FULL  ***

352 ZSTP = ZSTP + 16

354 PRINT : INPUT "ENTER TO CONTINUE:"; A$

356 CLS : PRINT HDR$: PRINT : PRINT

358 GOTO 220



600 REM * SQUARE FUNCTION *

602 CLS : PRINT : PRINT

604 PRINT "PREPARING DATA INPUT - PLEASE WAIT!"

610 FOR I = 0 TO Q / 2 - 1

620 C(0, I) = -1: S(0, I) = 0

630 NEXT

640 FOR I = Q / 2 TO Q - 1

650 C(0, I) = 1: S(0, I) = 0

660 NEXT

670 T0 = 1: T1 = 0

680 GOSUB 100

690 RETURN



990 END



1000 REM ***************************************

1002 REM *           MODIFY SPECTRUM           *

1004 REM ***************************************

1040 CLS : RTFLG = 0

1042 IF K6 <> -1 THEN 1096

1050 PRINT SPC(30); "MODIFY SPECTRUM MENU": PRINT : PRINT

1060 PRINT SPC(5); "1 = TRUNCATE SPECTRUM": PRINT

1062 PRINT SPC(5); "2 = BUTTERWORTH RESPONSE": PRINT

1064 PRINT SPC(5); "3 = GAUSSIAN RESPONSE": PRINT

1068 PRINT SPC(5); "6 = EXIT": PRINT

1070 PRINT SPC(10); "MAKE SELECTION :";

1080 A$ = INKEY$: IF A$ = "" THEN 1080

1082 A = VAL(A$): ON A GOSUB 1100, 1200, 1300, 1990, 1990, 1990

1084 GOSUB 200

1088 IF RTFLG = 1 THEN RETURN

1090 GOTO 1040

1096 INPUT "MUST TRANSFORM SIGNAL BEFORE MODIFYING SPECTRUM"; A$

1098 RETURN



1100 REM * TRUNCATE SPECTRUM *

1102 CLS : PRINT : PRINT

1104 INPUT "ENTER CUTOFF FREQUENCY"; A$

1110 FC0 = VAL(A$): IF FC0 = 0 OR FC0 > Q3 THEN 1104

1130 FOR I = FC0 TO Q - FC0

1140 C(T1, I) = 0: S(T1, I) = 0

1150 NEXT I

1194 RTFLG = 1: RETURN



1200 REM * BUTTERWORTH RESPONSE *

1202 CLS : PRINT : PRINT

1204 PRINT "ENTER THE 3db CUTOFF HARMONIC NUMBER (1 TO "; Q3; ")";

1206 INPUT A$

1208 FC0 = VAL(A$): IF FC0 = 0 OR FC0 > Q3 THEN 1204

1210 NP = 7: REM NUMBER OF POLES = NP

1220 FOR I = 1 TO Q3

1222 ATTN = 1 / SQR(1 + (I / FC0) ^ (2 * NP))

1224 C(T1, I) = ATTN * C(T1, I): S(T1, I) = ATTN * S(T1, I)

1226 C(T1, Q - I) = ATTN * C(T1, Q - I): S(T1, Q - I) = ATTN * S(T1, Q - I)

1228 NEXT I

1230 ATTN = 1 / SQR(1 + (Q2 / FC0) ^ (2 * NP))

1234 C(T1, Q2) = ATTN * C(T1, Q2)

1294 RTFLG = 1: RETURN



1300 REM * GAUSSIAN RESPONSE *

1302 CLS : PRINT : PRINT

1304 PRINT "ENTER THE 3db CUTOFF HARMONIC NUMBER (1 TO "; Q3; ")";

1306 INPUT A$

1308 FC0 = VAL(A$): IF FC0 = 0 OR FC0 > Q3 THEN 1304

1320 FOR I = 1 TO Q3

1322 ATTN = 1 / SQR(EXP(.3 * ((I / FC0) ^ 2)))

1324 C(T1, I) = ATTN * C(T1, I): S(T1, I) = ATTN * S(T1, I)

1326 C(T1, Q - I) = ATTN * C(T1, Q - I): S(T1, Q - I) = ATTN * S(T1, Q - I)

1328 NEXT I

1330 ATTN = 1 / SQR(EXP(.3 * ((Q2 / FC0) ^ 2)))

1334 C(T1, Q2) = ATTN * C(T1, Q2): S(T1, Q2) = ATTN * S(T1, Q2)

1394 RTFLG = 1: RETURN



1990 REM * EXIT MODIFY SPECTRUM ROUTINE *

1992 RTFLG = 1: RETURN





